#include "thread_pool.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h> // 提供 strerror 函数
#include <errno.h>	// 提供 errno 定义
#include <stdlib.h> // 提供 exit 函数
#include <fcntl.h>	// 定义O_RDONLY
#include <dirent.h> // dir
#include <stdio.h>
// 线程参数结构体
typedef struct
{
	char src_path[1024];
	char dest_path[1024];
} thread_arg_t;
thread_pool *pool;
// 文件拷贝函数
void *copy_file(void *arg)
{
	thread_arg_t *args = (thread_arg_t *)arg;

	printf("开始拷贝: %s -> %s\n", args->src_path, args->dest_path);

	FILE *src = fopen(args->src_path, "rb");
	if (src == NULL)
	{
		printf("无法打开源文件: %s (%s)\n", args->src_path, strerror(errno));
		// free(args);
		return NULL;
	}

	FILE *dest = fopen(args->dest_path, "wb");
	if (dest == NULL)
	{
		printf("无法创建目标文件: %s (%s)\n", args->dest_path, strerror(errno));
		fclose(src);
		// free(args);
		return NULL;
	}

	// 拷贝文件内容
	char buffer[4096];
	size_t bytes_read;
	while ((bytes_read = fread(buffer, 1, sizeof(buffer), src)) > 0)
	{
		fwrite(buffer, 1, bytes_read, dest);
	}

	fclose(src);
	fclose(dest);

	printf("完成拷贝: %s\n", args->src_path);
	// free(args); 线程池已完成释放
	return NULL;
}
// 遍历目录
void process_dir(const char *src_dir, const char *dest_dir)
{
	// 1.打开目录
	DIR *dir = opendir(src_dir);
	if (dir == NULL)
	{
		printf("无法打开源目录:%s (%s)\n", src_dir, strerror(errno));
		return;
	}
	struct dirent *entry; // 目录结构体
	struct stat st;				// 文件结构体
	// 创建目标目录 (如果不存在)
	mkdir(dest_dir, 0755);
	int thread_count = 0;									 // 复制
	while ((entry = readdir(dir)) != NULL) // readdir () 函数返回一个指向 dirent 结构的指针，该结构表示由 dirp 指向的目录流中的下一个目录项。
	{																			 // 当到达目录流的末尾或发生错误时，它返回 NULL。
		// 跳过.和..目录
		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
		{
			continue;
		}
		char src_path[1024];
		char dest_path[1023];
		snprintf(src_path, sizeof(src_path), "%s/%s", src_dir, entry->d_name);
		snprintf(dest_path, sizeof(dest_path), "%s/%s", dest_dir, entry->d_name);
		if (stat(src_path, &st) != 0)
		{
			printf("无法获取文件信息: %s (%s)\n", src_path, strerror(errno));
			continue;
		}
		// 如果是普通文件，创建线程进行拷贝
		if (S_ISREG(st.st_mode))
		{
			thread_arg_t *args = malloc(sizeof(thread_arg_t));
			if (args == NULL)
			{
				printf("内存分配失败\n");
				continue;
			}
			strncpy(args->src_path, src_path, sizeof(args->src_path));
			strncpy(args->dest_path, dest_path, sizeof(args->dest_path));

			if (add_task(pool, copy_file, args) != 0)
			{
				printf("无法添加线程任务 (%s)\n", strerror(errno));
				// free(args);
				continue;
			}

			thread_count++;
		}
		// 如果是目录，递归处理
		else if (S_ISDIR(st.st_mode))
		{
			process_dir(src_path, dest_path);
		}
	}
}

int main(int argc, char const *argv[])
{
	// 0.检查参数
	if (argc != 3)
	{
		printf("请指定源文件和目标文件\n");
		exit(0);
	}
	// 1, initialize the pool
	pool = malloc(sizeof(thread_pool));
	init_pool(pool, 5);

	printf("开始处理目录: %s -> %s\n", argv[1], argv[2]);
	process_dir(argv[1], argv[2]);
	// 等待所有线程完成
	shutdown_pool(pool);
	free(pool); // 释放线程池内存
	printf("文件处理完成\n");
	return 0;
}
